package com.an.blog.web.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSONObject;
import com.an.blog.service.IBlogUserService;
import com.an.blog.third.auth.AuthRequestUtils;
import com.an.blog.web.domain.BlogLoginForm;
import com.an.blog.web.domain.bo.BlogForgetUserBo;
import com.an.blog.web.domain.bo.BlogRegisterUserBo;
import com.an.blog.web.domain.vo.BlogUserWebVo;
import com.an.common.annotation.Log;
import com.an.common.annotation.RepeatSubmit;
import com.an.common.constant.BlogConstants;
import com.an.common.constant.MqConstants;
import com.an.common.core.controller.BaseController;
import com.an.common.core.domain.R;
import com.an.common.core.domain.bo.SendCodeBo;
import com.an.common.enums.BusinessType;
import com.an.producer.MqProducer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;


/**
 * 博客登录web控制器
 *
 * @author: Ann
 * @createDate: 2023/11/05
 * @version: 1.0.0
 */
@Slf4j
@Validated
@SaIgnore
@RestController
@RequiredArgsConstructor
@RequestMapping("/blog-web/oauth")
public class BlogLoginWebController extends BaseController {

    private final IBlogUserService blogUserService;

    private final MqProducer mqProducer;


    /**
     * 提供身份验证
     *
     * @return @return {@link R }<{@link String }>
     * @throws
     * @params @param source 源
     * @author: Ann
     * @createDate: 2023/11/05
     * @version: 1.0.0
     */
    @PostMapping("/render/{source}")
    public R<String> renderAuth(@PathVariable("source") String source) {
        log.info("进入renderAuth：" + source);
        AuthRequest authRequest = AuthRequestUtils.getAuthRequest(source);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        log.info(authorizeUrl);
        return R.ok("操作成功", authorizeUrl);
    }


    /**
     * 社会登录
     *
     * @param source          源
     * @param callback        回调
     * @param servletResponse servlet响应
     * @throws IOException ioexception
     * @author: Ann
     * @createDate: 2023/11/05 11:30:50
     * @version: 1.0.0
     */
    @RequestMapping("/callback/{source}")
    public void socialLogin(@PathVariable String source, AuthCallback callback,
                            HttpServletResponse servletResponse) throws IOException {
        log.info("进入callback：" + source + " callback params：" + JSONObject.toJSONString(callback));
        AuthRequest authRequest = AuthRequestUtils.getAuthRequest(source);
        AuthResponse<AuthUser> response = authRequest.login(callback);
        blogUserService.oauthLogin(response, source, callback, servletResponse);
    }


    /**
     * 注册
     *
     * @param registerUserBo 注册用户bo
     * @return {@link R }<{@link Map }<{@link String }, {@link Object }>>
     * @author: Ann
     * @createDate: 2023/11/05 11:30:43
     * @version: 1.0.0
     */
    @RepeatSubmit
    @PostMapping("/register")
    @Log(title = "用户注册", businessType = BusinessType.INSERT)
    public R<Map<String, Object>> register(@RequestBody @Validated BlogRegisterUserBo registerUserBo) {
        return R.ok(blogUserService.register(registerUserBo));
    }

    /**
     * 发送验证码
     *
     * @param sendCodeBo 发送代码业务对象
     * @return {@link R }<{@link Void }>
     * @author: Ann
     * @createDate: 2023/06/07 11:43:47
     * @version: 1.0.0
     */
    @PostMapping("/sendCode")
    @Log(title = "发送验证码", businessType = BusinessType.OTHER)
    @RepeatSubmit(interval = 60000, message = "请勿频繁请求验证码")
    public R<Void> sendCode(@RequestBody @Validated SendCodeBo sendCodeBo) {
        mqProducer.sendMessage(MqConstants.MAIL_EXCHANGE, MqConstants.MAIL_SEND_KEY, sendCodeBo);
        return R.ok();
    }

    /**
     * 登录
     *
     * @param blogLoginForm 博客登录表单
     * @return {@link R }<{@link Map }<{@link String },{@link Object }>>
     * @author: Ann
     * @createDate: 2023/06/01 21:53:52
     * @version: 1.0.0
     */
    @RepeatSubmit
    @PostMapping("/login")
    public R<Map<String, Object>> login(@RequestBody @Validated(BlogLoginForm.PasswordLogin.class) BlogLoginForm blogLoginForm) {
        return R.ok(blogUserService.login(blogLoginForm, BlogConstants.PWD_LOGIN));
    }

    /**
     * 邮箱验证码登录
     *
     * @param blogLoginForm 博客登录表单
     * @return {@link R }<{@link Map }<{@link String }, {@link Object }>>
     * @author: Ann
     * @createDate: 2023/08/22 11:22:26
     * @version: 1.0.0
     */
    @PostMapping("/emailCodeLogin")
    public R<Map<String, Object>> emailCodeLogin(@RequestBody @Validated(BlogLoginForm.CodeLogin.class) BlogLoginForm blogLoginForm) {
        return R.ok(blogUserService.login(blogLoginForm, BlogConstants.EMAIL_CODE_LOGIN));
    }


    /**
     * 忘记 PWD
     *
     * @param forgetUserBo 忘记用户 bo
     * @return {@link R }<{@link Void }>
     * @author Ann
     * @date 2024/08/12
     */
    @RepeatSubmit
    @PostMapping("/forgetPwd")
    @Log(title = "忘记密码", businessType = BusinessType.OTHER)
    public R<Void> forgetPwd(@Validated @RequestBody BlogForgetUserBo forgetUserBo) {
        return toAjax(blogUserService.forgetPwd(forgetUserBo));
    }


    @PostMapping("/logout")
    public R<Void> logout() {
        blogUserService.logout();
        return R.ok("退出成功");
    }

    /**
     * 让博客用户信息
     *
     * @return {@link R }<{@link BlogUserWebVo }>
     * @author: Ann
     * @createDate: 2023/08/28 20:03:34
     * @version: 1.0.0
     */
    @GetMapping("/getBlogUserInfo")
    @SaCheckLogin
    public R<BlogUserWebVo> getBlogUserInfo() {
        return blogUserService.getBlogUserInfo();
    }


}
